/*
 * This file Copyright (c) 2015. Walle.
 * (http://www.wallellen.com). All rights reserved.
 *
 *
 * This file is dual-licensed under both the
 * Walle Agreement (WA) and the GNU General Public License.
 * You may elect to use one or the other of these licenses.
 *
 * This file is distributed in the hope that it will be
 * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
 * Redistribution, except as permitted by whichever of the GPL
 * or WA you select, is prohibited.
 *
 * 1. For the GPL license (GPL), you can redistribute and/or
 * modify this file under the terms of the GNU General
 * Public License, Version 3, as published by the Free Software
 * Foundation.  You should have received a copy of the GNU
 * General Public License, Version 3 along with this program;
 * if not, write to the Free Software Foundation, Inc., 51
 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * 2. For the Walle Agreement (WA), this file
 * and the accompanying materials are made available under the
 * terms of the WA which accompanies this distribution, and
 * is available at http://www.wallellen.com/agreement.html
 *
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 */

package com.wallellen.parameter.service.impl;

import com.wallellen.core.auth.domain.LoginUser;
import com.wallellen.core.sql.query.DBSort;
import com.wallellen.core.sql.query.DataQuery;
import com.wallellen.core.sql.result.DataResult;
import com.wallellen.core.time.TimeTool;
import com.wallellen.parameter.dao.AloneparameterlocalDaoInter;
import com.wallellen.parameter.dao.ParameterDaoInter;
import com.wallellen.parameter.domain.AloneParameter;
import com.wallellen.parameter.domain.Aloneparameterlocal;
import com.wallellen.parameter.exception.KeyExistException;
import com.wallellen.parameter.service.ParameterServiceInter;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by walle on 12/12/15.
 */

@Service
public class ParameterServiceImpl
        implements ParameterServiceInter {

    @Resource
    private ParameterDaoInter parameterDao;

    @Resource
    private AloneparameterlocalDaoInter aloneparameterlocalDao;
    private static final Map<String, String> parameterCache = new HashMap();

    public boolean initConfig() {
        return false;
    }

    public boolean refreshCache() {
        parameterCache.clear();
        return true;
    }

    @Transactional
    public void deleteEntity(String entity, LoginUser user) {
        this.parameterDao.deleteEntity(this.parameterDao.getEntity(entity));
    }

    @Transactional
    public AloneParameter insertEntity(AloneParameter entity, String domain, LoginUser aloneUser)
            throws KeyExistException {
        if (isRepeatKey(entity.getPkey())) {
            throw new RuntimeException("参数键：" + entity.getPkey() + "，已存在！");
        }

        if (entity.getVtype().equals("1")) {
            entity.setRules("");
        }

        entity.setCtime(TimeTool.getTimeDate12());
        entity.setUtime(TimeTool.getTimeDate12());
        entity.setCuser(aloneUser.getId());
        entity.setMuser(aloneUser.getId());
        entity.setState("1");
        this.parameterDao.insertEntity(entity);
        return entity;
    }

    @Transactional
    public AloneParameter editEntity(AloneParameter entity, LoginUser aloneUser) {
        AloneParameter entity2 = getEntity(entity.getId());
        if ((!entity2.getPkey().equals(entity.getPkey())) && (isRepeatKey(entity.getPkey()))) {
            throw new RuntimeException("参数键：" + entity.getPkey() + "，已存在！");
        }

        if (entity.getVtype().equals("1")) {
            entity.setRules("");
        }

        entity2.setUtime(TimeTool.getTimeDate12());
        entity2.setMuser(aloneUser.getId());
        entity2.setName(entity.getName());

        entity2.setPkey(entity.getPkey());
        entity2.setPvalue(entity.getPvalue());
        entity2.setRules(entity.getRules());
        entity2.setDomain(entity.getDomain());
        entity2.setUserable(entity.getUserable());
        entity2.setComments(entity.getComments());
        entity2.setVtype(entity.getVtype());
        this.parameterDao.editEntity(entity2);
        return entity2;
    }

    public boolean isRepeatKey(String paramKey, String excludeParamId) {
        List paramList = null;
        if ((excludeParamId == null) || (excludeParamId.equals("")))
            paramList = this.parameterDao.findListByKey(paramKey.trim());
        else {
            paramList = this.parameterDao.findListByKeyAndExcludeParamId(paramKey.trim(), excludeParamId);
        }
        return paramList.size() > 0;
    }

    public boolean isRepeatKey(String paramKey) {
        return isRepeatKey(paramKey, null);
    }

    @Transactional
    public AloneParameter getEntity(String id) {
        if (id == null) {
            return null;
        }
        return this.parameterDao.getEntity(id);
    }

    public ParameterDaoInter getParameterDao() {
        return this.parameterDao;
    }

    public void setParameterDao(ParameterDaoInter parameterDao) {
        this.parameterDao = parameterDao;
    }

    public AloneparameterlocalDaoInter getAloneparameterlocalDao() {
        return this.aloneparameterlocalDao;
    }

    public void setAloneparameterlocalDao(AloneparameterlocalDaoInter aloneparameterlocalDao) {
        this.aloneparameterlocalDao = aloneparameterlocalDao;
    }

    @Transactional
    public List<Map<String, Object>> getTransParamList(String domainType) {
        String type = "";
        if (domainType.equals("1"))
            type = "alone";
        else if (domainType.equals("2"))
            type = "app";
        else if (domainType.equals("3")) {
            type = "ccs";
        }
        List<Map<String, Object>> list = this.parameterDao.getListByDomainType(type);

        for (Map<String, Object> map : list) {
            if (map.get("VTYPE").equals(Character.valueOf('2'))) {
                ArrayList enumList = new ArrayList();

                for (String enumStr : ((String) map.get("RULES")).split(",")) {
                    ArrayList kvList = new ArrayList();
                    for (String kvStr : enumStr.split(":")) {
                        kvList.add(kvStr);
                    }
                    enumList.add(kvList);
                }
                map.put("ENUMVALUE", enumList);
            }
        }
        return list;
    }

    @Transactional
    public AloneParameter findEntityByKey(String paramKey) {
        return this.parameterDao.findEntityByKey(paramKey.trim());
    }

    @Transactional
    public void setValue(String key, String pValue, LoginUser aloneUser) {
        AloneParameter entity = this.parameterDao.getEntityByKey(key);
        entity.setUtime(TimeTool.getTimeDate12());
        entity.setMuser(aloneUser.getId());
        entity.setPvalue(pValue);
        this.parameterDao.editEntity(entity);
        parameterCache.clear();
    }

    @Transactional
    public List<Map<String, Object>> getAllParameters() {
        DataQuery query = DataQuery.init(
                null,
                "Alone_Parameter a",
                "id,domain,name,pkey,pvalue,vtype,comments,rules");
        query.addSort(new DBSort("a.name", "asc"));
        query.setPagesize(200);
        DataResult result = null;
        try {
            result = query.search();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return result.getResultList();
    }

    @Transactional
    public List<Map<String, Object>> getUserParameters(String userid) {
        DataQuery query = DataQuery.init(
                null,
                "Alone_Parameter a left join ALONE_PARAMETER_LOCAL b on b.PARAMETERID=a.id",
                "a.id as id,a.domain as domain,a.name as name,a.pkey as pkey,a.pvalue as pvalue,a.vtype as vtype,a.comments as comments,a.rules as rules,b.pvalue as uservalue");
        query.addSort(new DBSort("a.name", "asc"));
        query.setPagesize(200);
        query.addSqlRule(" and USERABLE='1'");
        DataResult result = null;
        try {
            result = query.search();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

        for (Map node : result.getResultList()) {
            if ((node.get("USERVALUE") != null) && (node.get("USERVALUE").toString().trim().length() > 0)) {
                node.put("PVALUE", node.get("USERVALUE"));
            }
        }
        return result.getResultList();
    }

    @Transactional
    public void setUserValue(String key, String pValue, LoginUser aloneUser) {
        AloneParameter entity = this.parameterDao.getEntityByKey(key);
        if (entity == null) {
            throw new RuntimeException("参数不存在!");
        }
        if (entity.getUserable().equals("0")) {
            throw new RuntimeException("该参数不允许用户自定义！");
        }
        Aloneparameterlocal localPara = this.aloneparameterlocalDao.getEntityByUser(aloneUser.getId(), entity.getId());
        if (localPara == null) {
            localPara = new Aloneparameterlocal();
            localPara.setEuser(aloneUser.getId());
            localPara.setParameterid(entity.getId());
            localPara.setPvalue(pValue);
            this.aloneparameterlocalDao.insertEntity(localPara);
        } else {
            localPara.setPvalue(pValue);
            this.aloneparameterlocalDao.editEntity(localPara);
        }
        parameterCache.clear();
    }

    @Transactional
    public String getValue(String key) {
        if (parameterCache.containsKey(key)) {
            return (String) parameterCache.get(key);
        }
        AloneParameter entity = this.parameterDao.getEntityByKey(key);
        if (entity == null) {
            parameterCache.put(key, null);
            return null;
        }
        if (parameterCache.size() > 1000) {
            parameterCache.clear();
        }
        parameterCache.put(key, entity.getPvalue());
        return entity.getPvalue();
    }

    @Transactional
    public String getValue(String key, String userId) {
        AloneParameter entity = this.parameterDao.getEntityByKey(key);
        if (entity == null) {
            return null;
        }

        if (entity.getUserable().equals("1")) {
            Aloneparameterlocal localPara = this.aloneparameterlocalDao.getEntityByUser(userId, entity.getId());
            if (localPara != null) {
                return localPara.getPvalue();
            }
        }

        return getValue(key);
    }
}